package com.sdsmdg.harjot.vectormaster;

import com.sdsmdg.harjot.vectormaster.models.ClipPathModel;
import com.sdsmdg.harjot.vectormaster.models.GroupModel;
import com.sdsmdg.harjot.vectormaster.models.PathModel;
import com.sdsmdg.harjot.vectormaster.models.VectorModel;
import com.sdsmdg.harjot.vectormaster.utilities.LogUtil;
import com.sdsmdg.harjot.vectormaster.utilities.Utils;

import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.VectorElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Path;
import ohos.agp.utils.Matrix;
import ohos.app.Context;

/**
 * VectorMasterDrawable
 */
public class VectorMasterDrawable extends VectorElement {
    private Context context;
    private VectorModel vectorModel;
    private String path;
    private float offsetX = 0.0f;
    private float offsetY = 0.0f;
    private float scaleX = 1.0f;
    private float scaleY = 1.0f;
    private String TAG = "VECTOR_MASTER_DRAWABLE";
    private Matrix scaleMatrix;
    private int width = -1;
    private int height = -1;
    private float scaleRatio;
    private float strokeRatio;
    private int left = 0;
    private int top = 0;
    private int tempSaveCount;

    public VectorMasterDrawable(Context context, int xmlId) {
        super(context, xmlId);
        this.context = context;
        vectorModel = new XmlParser().buildVectorModel(context, xmlId);
    }

    /**
     * Set path
     *
     * @param path   path
     * @param width  width
     * @param height height
     * @param left   left
     * @param top    top
     */
    public void setPath(String path, int width, int height, int left, int top) {
        this.path = path;
        LogUtil.debug(TAG, path);
        vectorModel = new XmlParser().buildVectorModel(context, path);
        this.width = width;
        this.height = height;
        this.left = left;
        this.top = top;

        buildScaleMatrix();
        scaleAllPaths();
        scaleAllStrokes();
    }

    @Override
    public void drawToCanvas(Canvas canvas) {
        super.drawToCanvas(canvas);
        LogUtil.debug(TAG, "drawToCanvas");
        if (vectorModel == null) {
            return;
        }

        if (scaleMatrix == null) {
            int temp1 = Utils.vpToPx(context, (int) vectorModel.getWidth());
            int temp2 = Utils.vpToPx(context, (int) vectorModel.getHeight());

            setBounds(0, 0, temp1, temp2);
        }
        this.width = width;
        this.height = height;
        setAlpha(Utils.getAlphaFromFloat(vectorModel.getAlpha()));

        if (left != 0 || top != 0) {
            tempSaveCount = canvas.save();
            canvas.translate(left, top);
            vectorModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY);
            canvas.restoreToCount(tempSaveCount);
        } else {
            vectorModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY);
        }
    }

    @Override
    public void setAlpha(int alpha) {
        if (vectorModel != null) {
            vectorModel.setAlpha(Utils.getAlphaFromInt(alpha));
        }
    }

    @Override
    public int getAlpha() {
        return super.getAlpha();
    }

    @Override
    public int getHeight() {
        return Utils.vpToPx(context, (int) vectorModel.getHeight());
    }

    @Override
    public int getWidth() {
        return Utils.vpToPx(context, (int) vectorModel.getHeight());
    }

    private void buildScaleMatrix() {
        scaleMatrix = new Matrix();

        scaleMatrix.postTranslate(width / 2 - vectorModel.getViewportWidth() / 2,
                height / 2 - vectorModel.getViewportHeight() / 2);

        float widthRatio = width / vectorModel.getViewportWidth();
        float heightRatio = height / vectorModel.getViewportHeight();
        float ratio = Math.min(widthRatio, heightRatio);

        scaleRatio = ratio;

        scaleMatrix.postScale(ratio, ratio, width / 2, height / 2);
    }

    private void scaleAllPaths() {
        vectorModel.scaleAllPaths(scaleMatrix);
    }

    private void scaleAllStrokes() {
        strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight());
        vectorModel.scaleAllStrokeWidth(strokeRatio);
    }

    /**
     * Get full path
     *
     * @return fullPath
     */
    public Path getFullPath() {
        Path fullPath = null;
        if (vectorModel != null) {
            fullPath = vectorModel.getFullpath();
        }
        return fullPath;
    }

    /**
     * Get GroupModel from model name
     *
     * @param name model name
     * @return GroupModel
     */
    public GroupModel getGroupModelByName(String name) {
        GroupModel gModel = null;
        for (GroupModel groupModel : vectorModel.getGroupModels()) {
            if (Utils.isEqual(groupModel.getName(), name)) {
                return groupModel;
            } else {
                gModel = groupModel.getGroupModelByName(name);
                if (gModel != null) {
                    return gModel;
                }
            }
        }
        return gModel;
    }

    /**
     * Get PathModel from model name
     *
     * @param name model name
     * @return PathModel
     */
    public PathModel getPathModelByName(String name) {
        PathModel pModel = null;
        for (PathModel pathModel : vectorModel.getPathModels()) {
            if (Utils.isEqual(pathModel.getName(), name)) {
                return pathModel;
            }
        }
        for (GroupModel groupModel : vectorModel.getGroupModels()) {
            pModel = groupModel.getPathModelByName(name);
            if (pModel != null && Utils.isEqual(pModel.getName(), name)) {
                return pModel;
            }
        }
        return pModel;
    }

    /**
     * Get ClipPathModel from model name
     *
     * @param name model name
     * @return ClipPathModel
     */
    public ClipPathModel getClipPathModelByName(String name) {
        ClipPathModel cModel = null;
        for (ClipPathModel clipPathModel : vectorModel.getClipPathModels()) {
            if (Utils.isEqual(clipPathModel.getName(), name)) {
                return clipPathModel;
            }
        }
        for (GroupModel groupModel : vectorModel.getGroupModels()) {
            cModel = groupModel.getClipPathModelByName(name);
            if (cModel != null && Utils.isEqual(cModel.getName(), name)) {
                return cModel;
            }
        }
        return cModel;
    }

    /**
     * Update view
     */
    public void update() {
        setVisible(true, true);
    }

    public float getScaleRatio() {
        return scaleRatio;
    }

    public float getStrokeRatio() {
        return strokeRatio;
    }

    public Matrix getScaleMatrix() {
        return scaleMatrix;
    }

    public float getOffsetX() {
        return offsetX;
    }

    public void setOffsetX(float offsetX) {
        this.offsetX = offsetX;
        update();
    }

    public float getOffsetY() {
        return offsetY;
    }

    public void setOffsetY(float offsetY) {
        this.offsetY = offsetY;
        update();
    }

    public float getScaleX() {
        return scaleX;
    }

    public void setScaleX(float scaleX) {
        this.scaleX = scaleX;
        update();
    }

    public float getScaleY() {
        return scaleY;
    }

    public void setScaleY(float scaleY) {
        this.scaleY = scaleY;
        update();
    }
}
